using System;
using Qyoto;
using System.IO;
using System.Collections.Generic;
using Clandestine.Base;
using Clandestine.Engines.Field;

namespace Shlick
{
	public class ObjectsTab : QWidget
	{
		private Ui_ObjectsTab ui;
		public MapDocument MapDocument { get; private set; }
		private LayerTreeWidget levelsWidget;
		private QListView listWidget;
		private ObjectListModel listModel;
		
		public ObjectsTab(MapDocument mapDocument) : base()
		{
			this.ui = new Ui_ObjectsTab();
			this.ui.SetupUi(this);
			this.MapDocument = mapDocument;
			
			// Level Widget
			QVBoxLayout vbox = new QVBoxLayout(this.ui.frameLevels);
			vbox.SetContentsMargins(0, 0, 0, 0);
			levelsWidget = new LayerTreeWidget(this, this.MapDocument, LayerTreeMode.Level, true);
			vbox.AddWidget(levelsWidget);
			
			// Prepare Object List Model!
			listModel = new ObjectListModel();
			listModel.Add(new ObjectListNewItem(":/tango/scalable/actions/document-new.svg"));
			
			// Prepare Object List Widget
			vbox = new QVBoxLayout(this.ui.frameObjectList);
			vbox.SetContentsMargins(0, 0, 0, 0);
			listWidget = new QListView() {
				viewMode = QListView.ViewMode.IconMode,
				IsWrapping = false
			};
			listWidget.SetModel(listModel);
			vbox.AddWidget(listWidget);
			
			// Populate the Object List
			// Todo: search subdirs
			foreach (string path in Directory.GetFiles("objects/"))
				if (Path.GetExtension(path) == ".xml")
				{
					string iconPath = path + ".png";
					listModel.Add(new ObjectListItem(Path.GetFileNameWithoutExtension(path), path, iconPath));
				}
				
			// Signals
			Connect(listWidget, SIGNAL("pressed(QModelIndex)"), this, SLOT("mouseClicked(QModelIndex)"));
			
			// Events
			this.MapDocument.ToolManager.Tools[ToolTypes.ObjectAdd].ToolComplete += delegate () {
				listWidget.SetCurrentIndex(new QModelIndex()); // clear selection.
			};
		}
		
				// When tab is focused
		public void Activated()
		{
			// Make sure that no object is selected in list and set to ObjectSelect
			listWidget.SetCurrentIndex(new QModelIndex());
			this.MapDocument.ToolManager.SwitchToTool(ToolTypes.ObjectSelect);
		}
		
		[Q_SLOT("mouseClicked(QModelIndex)")]
		private void mouseClicked(QModelIndex index)
		{
			if (!index.IsValid())
				return;
			
			this.itemSelected(((ObjectListItem)index.InternalPointer()));
		}
		
		private void itemSelected(ObjectListItem item)
		{
			// Pass the selected object ['s delegate]
			((ObjectAddTool)this.MapDocument.ToolManager.Tools[ToolTypes.ObjectAdd]).CreateObjectDelegate = item.GetDelegate();
			
			// Change to tool
			this.MapDocument.ToolManager.OpenNewTool(ToolTypes.ObjectAdd);
		}
		
		private class ObjectListItem
		{
			public string Text { get; set; }
			public string Path { get; set; }
			public string IconPath { get; set; }
			public QIcon Icon { get; set; }
			
			protected ObjectListItem() { }
			public ObjectListItem(string text, string path, string iconpath)
			{
				this.Text = text;
				this.Path = path;
				
				if (File.Exists(iconpath))
				{
					this.IconPath = iconpath;
					this.Icon = new QIcon(this.IconPath);
				}
				else
					this.Icon = new QIcon();
			}
			
			public virtual CreateObjectDelegate GetDelegate()
			{
				return delegate (Level level) {
					return level.AddObject(this.Path);
				};
			}
		}
		
		// poorly named, but special class for the "Add New Object" object.
		private class ObjectListNewItem : ObjectListItem
		{
			public ObjectListNewItem(string iconpath)
			{	
				base.Text = "Add New Object";
				base.Path = string.Empty;
				base.Icon = new QIcon(iconpath);
			}
			
			public override CreateObjectDelegate GetDelegate()
			{
				return delegate (Level level) {
					return level.AddObject();
				};
			}
		}
		
		private class ObjectListModel : QAbstractItemModel
		{
			private List<ObjectListItem> items = new List<ObjectListItem>();
			
			public void Add(ObjectListItem item)
			{
				this.items.Add(item);
			}
			
			public override QModelIndex Index(int row, int column, QModelIndex parent)
			{
				return this.CreateIndex(row, column, items[row]);
			}
			
			// Shouldn't have to implement this D: Bindings problem?
			public override QModelIndex Parent (QModelIndex child)
			{
				return new QModelIndex();
			}
			
			// Or this
			public override int ColumnCount (QModelIndex parent)
			{
				return 1;
			}
			
			public override QVariant Data (QModelIndex index, int role)
			{
				if (index.Row() >= items.Count)
					return new QVariant();
			
				// Text or icon?
				if (role == (int)ItemDataRole.DisplayRole) 
					return new QVariant(items[index.Row()].Text);
				else if (role == (int)ItemDataRole.DecorationRole)
					return new QVariant(items[index.Row()].Icon);
				else 
					return new QVariant();
			}
	
			public override int RowCount (QModelIndex parent)
			{
				return this.items.Count;
			}
		}
	}
}

